package com.hadoop.project.entity.constant;

import com.hadoop.project.entity.po.TabRank;
import com.hadoop.project.entity.po.UserFlavor;
import com.hadoop.project.entity.po.VideoRank;
import com.hadoop.project.entity.hbase.ProcessRes;
import com.hadoop.project.utils.Processor;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ZhiGeConstant {

    /**
     * 如果你要写入文件 改为true 不推荐
     */
    public static final Boolean needSaveToZhiGe = false;
    public static final String o                = ";";

    public static void saveDataInZhiGeDesktop(ProcessRes processRes) throws Exception {

        String YourPath = "C:\\Users\\244521\\Desktop\\";

        String tabRankFilePath    = YourPath + "tab-rank.txt";
        String userFlavorFilePath = YourPath + "user-flavor.txt";
        String videoRankFilePath  = YourPath + "video-rank.txt";

        Boolean writeTabRank    = true;
        Boolean writeUserFlavor = true;
        Boolean writeVideoRank  = true;


        // --- 进度条逻辑 ---
        // 1. 获取所有列表（进行 null 检查）
        List<TabRank> tabRankList = processRes.getTabRankList() != null ? processRes.getTabRankList() : new ArrayList<>();
        List<UserFlavor> userFlavorList = processRes.getUserFlavorList() != null ? processRes.getUserFlavorList() : new ArrayList<>();
        List<VideoRank> videoRankList = processRes.getVideoRankList() != null ? processRes.getVideoRankList() : new ArrayList<>();

        // 2. 计算总项目数 (仅计算需要写入的列表)
        int totalItems = 0;
        if (writeTabRank) totalItems += tabRankList.size();
        if (writeUserFlavor) totalItems += userFlavorList.size();
        if (writeVideoRank) totalItems += videoRankList.size();

        int processedItems = 0;

        if (totalItems == 0) {
            System.out.println("没有数据需要保存。");
            return; // 如果没有项目，直接返回
        }

        System.out.println("开始保存数据...");
        updateProgressBar(processedItems, totalItems);


        // --- 写入逻辑 ---
        // 这里主要干了 写入文件 和 进度条
        // 改进：将 BufferedWriter 的创建移到循环外部，提高效率
        // 改进：为每个文件写入过程添加进度更新

        if (writeTabRank && !tabRankList.isEmpty()) {
            // 使用 try-with-resources 确保 writer 被正确关闭
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(tabRankFilePath, true))) { // true 表示追加模式
                for (TabRank tabRank : tabRankList) {
                    try {
                        // 确保数据不为 null，避免 NullPointerException
                        String idStr = tabRank.getId() != null ? tabRank.getId().toString() : "null";
                        String tnameStr = tabRank.getTname() != null ? tabRank.getTname() : "null";
                        String cntStr = tabRank.getCnt() != null ? tabRank.getCnt().toString() : "null";

                        String str = idStr + o + tnameStr + o + cntStr;
                        writer.write(str);
                        writer.newLine();

                        processedItems++; // 更新已处理的项目数
                        updateProgressBar(processedItems, totalItems); // 更新进度条显示

                    } catch (Exception e) {
                        // 打印错误，但继续处理下一个条目，并确保进度条行被新行覆盖
                        System.err.println("\n处理 TabRank 时出错: " + (tabRank.getId() != null ? tabRank.getId() : "未知ID") + " - " + e.getMessage());
                        // 如果需要，可以在这里增加错误计数器或决定是否中止
                    }
                }
            } catch (IOException e) { // 捕获文件操作的 IO 异常
                System.err.println("\n写入文件 " + tabRankFilePath + " 时出错: " + e.getMessage());
                throw e; // 可以选择重新抛出，让调用者处理
            }
        }

        if (writeUserFlavor && !userFlavorList.isEmpty()) {
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(userFlavorFilePath, true))) {
                for (UserFlavor userFlavor : userFlavorList) {
                    try {
                        String idStr = userFlavor.getId() != null ? userFlavor.getId().toString() : "null";
                        String uidStr = userFlavor.getUid() != null ? String.valueOf(userFlavor.getUid()) : "null";
                        String tnameStr = userFlavor.getTname() != null ? userFlavor.getTname() : "null";
                        // 对于 double，可以直接转换，或者格式化
                        String tpercentStr = String.valueOf(userFlavor.getTpercent());

                        String str = idStr + o + uidStr + o + tnameStr + o + tpercentStr;
                        writer.write(str);
                        writer.newLine();

                        processedItems++;
                        updateProgressBar(processedItems, totalItems);

                    } catch (Exception e) {
                        System.err.println("\n处理 UserFlavor 时出错: " + (userFlavor.getId() != null ? userFlavor.getId() : "未知ID") + " - " + e.getMessage());
                    }
                }
            } catch (IOException e) {
                System.err.println("\n写入文件 " + userFlavorFilePath + " 时出错: " + e.getMessage());
                throw e;
            }
        }

        if (writeVideoRank && !videoRankList.isEmpty()) {
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(videoRankFilePath, true))) {
                for (VideoRank videoRank : videoRankList) {
                    try {
                        String idStr = videoRank.getId() != null ? videoRank.getId().toString() : "null";

                        String videoIdStr = videoRank.getVid() != null ? String.valueOf(videoRank.getVid()) : "null";
                        String viewsStr = videoRank.getViews() != null ? videoRank.getViews().toString() : "null";

                        String str = idStr + o + videoIdStr + o + viewsStr;
                        writer.write(str);
                        writer.newLine();

                        processedItems++;
                        updateProgressBar(processedItems, totalItems);

                    } catch (Exception e) {
                        System.err.println("\n处理 VideoRank 时出错: " + (videoRank.getId() != null ? videoRank.getId() : "未知ID") + " - " + e.getMessage());
                    }
                }
            } catch (IOException e) {
                System.err.println("\n写入文件 " + videoRankFilePath + " 时出错: " + e.getMessage());
                throw e;
            }
        }

        // 确保进度条最后显示 100% 并换行
        // updateProgressBar(processedItems, totalItems); // 最后一次循环已更新
        System.out.println(); // 在进度条完成后换行
        System.out.println("数据保存完成。");
    }

    private static final int PROGRESS_BAR_WIDTH = 50; // 进度条的宽度（字符数）

    private static void updateProgressBar(int current, int total) {
        if (total <= 0) return; // 防止除以零

        // 确保 current 不会超过 total (虽然理论上不应该发生)
        current = Math.min(current, total);

        int percentage = (int) (((double) current / total) * 100);
        int filledWidth = (int) (PROGRESS_BAR_WIDTH * percentage / 100.0);
        int emptyWidth = PROGRESS_BAR_WIDTH - filledWidth;

        StringBuilder bar = new StringBuilder();
        bar.append('[');
        for (int i = 0; i < filledWidth; i++) {
            bar.append('=');
        }
        // 可以用 '>' 表示当前进度点
        if (filledWidth < PROGRESS_BAR_WIDTH && current > 0) {
            bar.setCharAt(bar.length() - 1, '>'); // 将最后一个 '=' 替换为 '>'
        }

        for (int i = 0; i < emptyWidth; i++) {
            bar.append(' ');
        }
        bar.append(']');

        // \r 回车符，将光标移到行首，实现原地更新效果
        // String.format 用于格式化输出，%3d 表示整数占3位宽度，右对齐
        // 在末尾添加一些空格，以覆盖上一行可能更长的内容
        String output = String.format("\r保存进度: %s %3d%% (%d/%d)   ", bar.toString(), percentage, current, total);
        System.out.print(output);

        // 注意：这里不使用 System.out.println()，因为它会换行
        // 换行将在所有任务完成后进行
    }

    public static void writeInFile(ProcessRes processRes){
        try {
            ZhiGeConstant.saveDataInZhiGeDesktop(processRes);
            log.info("\n\n写入智哥文件成功");
        } catch (Exception e) {
            log.error("\n\n写入智哥文件失败");
        }
    }
}
